package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.tanhua.domain.db.*;
import com.tanhua.domain.vo.ReportVo;
import com.tanhua.domain.vo.SoulOptionsVo;
import com.tanhua.domain.vo.SoulQuestionListVo;
import com.tanhua.domain.vo.SoulQuestionsVo;
import com.tanhua.dubbo.api.*;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class SoulService {
    @Reference
    private SoulQuestionLevelApi soulQuestionLevelApi;
    @Reference
    private SoulQuestionContentApi soulQuestionContentApi;
    @Reference
    private SoulQuestionStatusApi soulQuestionStatusApi;
    @Reference
    private SoulQuestionOptionsApi soulQuestionOptionsApi;
    @Reference
    private SoulQuestionReportApi soulQuestionReportApi;
    @Reference
    private UserInfoApi userInfoApi;
    
    
    /**
     * 接口名称：测灵魂-问卷列表
     * v1.1 加入Redis缓存机制
     */
    @Cacheable(value = "soulQuestionList", key = "#userId")
    public List<SoulQuestionListVo> soulQuestionList(Long userId) {
        //0.创建一个空列表准备封装要返回的数据
        List<SoulQuestionListVo> listVo = new ArrayList<>();
        
        //1.查询出所有 问卷等级划分的数据 ，得到List形式的结果
        List<SoulQuestionLevel> levelList = soulQuestionLevelApi.findAll();
        
        //2.对第一步得到的结果进行遍历（目标是获得接口要返回的数据）
        for (SoulQuestionLevel soulQuestionLevel : levelList) {
            
            //2.1 获取等级
            String level = soulQuestionLevel.getLevel();
            
            //2.2 根据等级去问题内容表查找对应等级的所有问题题目
            List<SoulQuestionContent> questionContents = soulQuestionContentApi.findByLevel(level);
            
            //2.3 创建一个空列表，准备装问题题目和对应的选项数据
            List<SoulQuestionsVo> questionContentsVo = new ArrayList<>();
            
            //2.4 对获取的题目列表进行遍历（目标是获得一个完整的问题信息（题目内容，题目id，题目对应的所有选项信息））
            for (SoulQuestionContent questionContent : questionContents) {
                
                //2.4.1 得到题目对应的id
                Long contentId = questionContent.getId();
                
                //2.4.2 根据题目id去题目选项表里查找该问题的所有选项
                List<SoulQuestionOptions> optionsList = soulQuestionOptionsApi.findByContentId(contentId);
                
                //2.4.3 创建一个空列表，准备装题目对应的选项数据
                ArrayList<SoulOptionsVo> optionsVo = new ArrayList<>();
                
                //2.4.4 对2.4.2中问题的所有选项进行遍历（目标是获得一个题目对应的所有选项数据（选项编号、选项内容））
                for (SoulQuestionOptions options : optionsList) {
                    //把选项id和选型的内容放到2.4.3的空列表里
                    optionsVo.add(new SoulOptionsVo(options.getOptionId(), options.getOptionContent()));
                }
                
                //2.4.5 把题目id，题目内容，题目选项数据放到2.3中的空列表
                questionContentsVo.add(new SoulQuestionsVo(questionContent.getId().toString(), questionContent.getQuestion(), optionsVo));
            }
            
            //对isLocke属性进行类型转换（Boolean转Integer）
            Boolean isLock = true;
            Integer isLockInter;
            //报告id做非空校验（前端接收该项可以为null）
            Integer reportId = null;
            String reportIdStr = null;
            
            //2.5 根据用户id去用户问题状态表里获取所有状态数据
            List<SoulQuestionStatus> soulQuestionStatus = soulQuestionStatusApi.findByUserId(userId);
            
            if (soulQuestionStatus != null && soulQuestionStatus.size() > 0) {
                //2.6 获取对应等级的状态信息
                for (SoulQuestionStatus status : soulQuestionStatus) {
                    if (status.getLevel().equals(level)) {
                        reportId = status.getReportId();
                        isLock = status.getIsLock();
                        if (level.equals("初级")) {
                            isLock = false;
                        }
                    }
                }
            } else if (level.equals("初级")) {
                isLock = false;//初级一定是解锁的
            }
            
            if (isLock) {
                isLockInter = 1;//未解锁
            } else {
                isLockInter = 0;//已经解锁
            }
            
            if (reportId != null) {
                reportIdStr = reportId.toString();
            }
            
            //2.7 根据 问卷等级id，问卷名称，问卷等级封面，问卷等级、问卷的星别、问题（题目内容、选项编号、选项内容）、等级是否解锁、等级对应的报告id属性创建对象放入创建的空Vo里
            listVo.add(new SoulQuestionListVo(soulQuestionLevel.getId().toString(), soulQuestionLevel.getName(), soulQuestionLevel.getCover(), level, soulQuestionLevel.getStar(), questionContentsVo, isLockInter, reportIdStr));
        }
        return listVo;
    }
    
    
    /**
     * 测灵魂-提交问卷
     * v1.1 增加Redis缓存机制（注意：此处提交报告才删除缓存）
     */
    @CacheEvict(value = "soulQuestionList", allEntries = true)
    public ResponseEntity<Object> submitAnswer(Long userId, String answers) {
        
        //1.解析JSON成为List<Map<String, String>>
        JSONObject jsonObject = JSON.parseObject(answers);
        Object answers_result = jsonObject.get("answers");
        String s = JSON.toJSONString(answers_result, SerializerFeature.WriteClassName);
        List<Map<String, String>> answerList = JSON.parseObject(s, List.class);
        
        
        Integer levelScore = 0;
        String questionId = null;
        String optionId;
        String questionLevel;
        
        //2.遍历List<Map<String, String>>获取问题编号和用户回答此问题的选项，得到该问题的总分
        for (Map<String, String> map : answerList) {
            //获取问题id和选项id，再据此得到此选项的分数
            questionId = map.get("questionId");
            optionId = map.get("optionId");
            Integer score = soulQuestionOptionsApi.findScore(Long.parseLong(questionId), optionId);
            
            //分数累加到levelScore
            levelScore += score;
        }
        
        //3.获取问题所属问卷的等级
        questionLevel = soulQuestionContentApi.findQuestionLevel(Long.parseLong(questionId));
        
        
        //4.根据得分，得出报告
        String id;
        if (levelScore < 21) {
            id = "1";
        } else if (levelScore <= 40) {
            id = "2";
        } else if (levelScore <= 55) {
            id = "3";
        } else {
            id = "4";
        }
        
        
        SoulQuestionStatus soulQuestionStatus = new SoulQuestionStatus();
        soulQuestionStatus.setUserId(userId);
        soulQuestionStatus.setLevel(questionLevel);
        soulQuestionStatus.setLevelScore(levelScore);
        soulQuestionStatus.setIsLock(false);
        soulQuestionStatus.setReportId(Integer.valueOf(id));
        
        //5.报告id、得分、对应等级保存到数据库
        soulQuestionStatusApi.saveReportId(soulQuestionStatus);
        
        
        //6. 解锁下一等级（最高解锁到高级）
        SoulQuestionStatus status = new SoulQuestionStatus();
        status.setUserId(userId);
        if (!questionLevel.equals("高级")) {
            switch (questionLevel) {
                case "初级":
                    status.setLevel("中级");
                    status.setIsLock(false);
                    break;
                case "中级":
                    status.setLevel("高级");
                    status.setIsLock(false);
                    break;
                default:
                    break;
            }
            soulQuestionStatusApi.unlockLevel(status);
        }
        return ResponseEntity.ok(id);
    }
    
    
    /**
     * 测灵魂-查看结果
     * <p>
     * 根据报告id查看报告结果
     */
    public ResponseEntity<Object> viewReport(Long userId, Long reportId) {
        //1.根据报告id查询报告
        SoulQuestionReport report = soulQuestionReportApi.findReport(reportId);
        //2.创建要返回的报告Vo的对象
        ReportVo reportVo = new ReportVo();
        
        //3.设置报告Vo的里的报告内容和报告封面
        reportVo.setConclusion(report.getReportContent());
        reportVo.setCover(report.getCover());
        
        //4. 创建一个List<Map<String,String>>来存放维度信息
        List<Map<String, String>> list = new ArrayList<>();
        
        //5. 获取各个维度对应的数据（4个维度），并放到4里面的列表里
        String lat = report.getLat();
        String[] split = lat.split(",");
        for (String s : split) {
            Map<String, String> dimensions = new HashMap<>();
            String[] s2 = s.split("=");
            dimensions.put("key", s2[0]);
            dimensions.put("value", s2[1]);
            list.add(dimensions);
        }
        //6.设置报告Vo里的纬度数据
        reportVo.setDimensions(list);
        
        //7. 根据报告id，在用户等级状态表里找推荐用户，得到的是推荐的用户id列表
        List<Long> similarYouList = soulQuestionStatusApi.findSimilarYou(userId, reportId);
        
        //8.创建一个 List<Map<String, Object>>装推荐的用户id和头像
        List<Map<String, Object>> similarUserInfoList = new ArrayList<>();
        
        //9.遍历7里的列表，把推荐用户id和头像放入8里的列表，然后再把8里的列表设置到报告Vo里
        if (similarYouList != null && similarYouList.size() > 0) {
            for (Long similarUserId : similarYouList) {
                UserInfo userInfo = userInfoApi.findById(similarUserId);
                Map<String, Object> similarYouMap = new HashMap<>();
                similarYouMap.put("id", userInfo.getId().intValue());
                similarYouMap.put("avatar", userInfo.getAvatar());
                similarUserInfoList.add(similarYouMap);
            }
            reportVo.setSimilarYou(similarUserInfoList);
        }
        return ResponseEntity.ok(reportVo);
    }
}
    
   
    

